package ferp.android.services;

import ferp.core.card.Card;
import ferp.core.game.Game;

/**
 * User: olegs
 * Date: 08/05/2014 12:03
 */
public class ServiceProxy
{
  public static void preallocate(IResolverService2 service) throws ServiceException
  {
    try
    {
      checkStatus(service, service.preallocate(), "preallocate");
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  public static void initialize(IResolverService2 service, int evaluator, int declarer, int starter, int trump, int hand0, int hand1, int hand2, byte talon0, byte talon1, int dropReal, int dropGuessed, int round, boolean open, boolean rostov, Game.ServiceData sd) throws ServiceException
  {
    try
    {
      checkStatus(service, service.initialize(evaluator, declarer, starter, trump, hand0, hand1, hand2, talon0, talon1, dropReal, dropGuessed, round, open, rostov), "initialize");

      sd.memory = service.getAvailableMemory();
      checkStatus(service, sd.memory, "getAvailableMemory");

      sd.nodes = service.getNodePoolCapacity();
      checkStatus(service, sd.nodes, "getNodePoolCapacity");

      sd.moves = service.getMovePoolCapacity();
      checkStatus(service, sd.moves, "getMovePoolCapacity");
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  public static int getBestScore(IResolverService2 service) throws ServiceException
  {
    try
    {
      int score = service.getBestScore();

      checkStatus(service, score, "getBestScore");

      return score;
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  public static byte getBestMove(IResolverService2 service, int level, int hand, int trick, int cardInHand) throws ServiceException
  {
    try
    {
      byte move = service.getBestMove(level, hand, trick, cardInHand);

      checkStatus(service, move, "getBestMove");

      if (!Card.isValidIndex(move))
        throw new ServiceException("getBestMove returned " + move + "\n" + service.getExceptionTrace());

      return move;
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  public static void solve(IResolverService2 service) throws ServiceException
  {
    try
    {
      checkStatus(service, service.solve(), "solve");
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  public static void advance(IResolverService2 service, int hand, int trick) throws ServiceException
  {
    try
    {
      checkStatus(service, service.advance(hand, trick), "advance");
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  public static void recalculateOnNextSolve(IResolverService2 service, int hand0, int hand1, int hand2, int trick) throws ServiceException
  {
    try
    {
      checkStatus(service, service.recalculateOnNextSolve(hand0, hand1, hand2, trick), "recalculateOnNextSolve");
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  public static int getSpeed(IResolverService2 service) throws ServiceException
  {
    try
    {
      int speed = service.getSpeed();

      checkStatus(service, speed, "getSpeed");

      return speed;
    }
    catch (ServiceException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      throw new ServiceException(e);
    }
  }

  private static void checkStatus(IResolverService2 service, long status, String method) throws ServiceException
  {
    if (status <= 0)
      switch ((int)status)
      {
        case ResolverService2.OK:
          break;

        case ResolverService2.OUT_OF_MEMORY:
          throw new ServiceException(method + " failed due to out of memory exception in service", status);

        default:
          try
          {
            throw new ServiceException(method + " returned " + status + "\n" + service.getExceptionTrace(), status);
          }
          catch (ServiceException e)
          {
            throw e;
          }
          catch (Exception e)
          {
            throw new ServiceException(e);
          }
      }
  }
}
